package org.proteored.miapeapi.xml.gi.adapter;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.proteored.miapeapi.cv.ControlVocabularyManager;
import org.proteored.miapeapi.cv.ge.ElectrophoresisType;
import org.proteored.miapeapi.interfaces.Adapter;
import org.proteored.miapeapi.interfaces.Algorithm;
import org.proteored.miapeapi.interfaces.DateAdapter;
import org.proteored.miapeapi.interfaces.MiapeDate;
import org.proteored.miapeapi.interfaces.Project;
import org.proteored.miapeapi.interfaces.ge.GEContact;
import org.proteored.miapeapi.interfaces.gi.AnalysisDesign;
import org.proteored.miapeapi.interfaces.gi.DataAnalysis;
import org.proteored.miapeapi.interfaces.gi.DataExtraction;
import org.proteored.miapeapi.interfaces.gi.DataReporting;
import org.proteored.miapeapi.interfaces.gi.GIAdditionalInformation;
import org.proteored.miapeapi.interfaces.gi.ImageAnalysisSoftware;
import org.proteored.miapeapi.interfaces.gi.ImageGelInformatics;
import org.proteored.miapeapi.interfaces.gi.ImagePreparationStep;
import org.proteored.miapeapi.interfaces.gi.ImageProcessing;
import org.proteored.miapeapi.interfaces.gi.ImageProcessingStep;
import org.proteored.miapeapi.interfaces.gi.MiapeGIDocument;
import org.proteored.miapeapi.xml.gi.autogenerated.GIAnalysisDesign;
import org.proteored.miapeapi.xml.gi.autogenerated.GIDataAnalysis;
import org.proteored.miapeapi.xml.gi.autogenerated.GIDataExtraction;
import org.proteored.miapeapi.xml.gi.autogenerated.GIDataReporting;
import org.proteored.miapeapi.xml.gi.autogenerated.GIImage;
import org.proteored.miapeapi.xml.gi.autogenerated.GIImagePreparationStep;
import org.proteored.miapeapi.xml.gi.autogenerated.GIImageProcessing;
import org.proteored.miapeapi.xml.gi.autogenerated.GIImageProcessingAlgorithmType;
import org.proteored.miapeapi.xml.gi.autogenerated.GIMIAPEGI;
import org.proteored.miapeapi.xml.gi.autogenerated.GIProcessingInputImage;
import org.proteored.miapeapi.xml.gi.autogenerated.MIAPESoftwareType;
import org.proteored.miapeapi.xml.gi.autogenerated.ObjectFactory;
import org.proteored.miapeapi.xml.gi.autogenerated.ParamType;
import org.proteored.miapeapi.xml.gi.util.GIControlVocabularyXmlFactory;

/**
 * Implementation of {@link GIMIAPEGI} from a {@link MiapeGIDocument} object.
 * 
 * @author Salva
 * 
 */
public class MiapeGiXMLAdapter implements Adapter<GIMIAPEGI> {
	private final ObjectFactory factory;
	private final MiapeGIDocument document;
	private final GIControlVocabularyXmlFactory cvFactory;

	public MiapeGiXMLAdapter(MiapeGIDocument document,
			ControlVocabularyManager controlVocabularyUtil) {
		this.factory = new ObjectFactory();
		this.document = document;
		this.cvFactory = new GIControlVocabularyXmlFactory(factory, controlVocabularyUtil);
	}

	@Override
	public GIMIAPEGI adapt() {
		GIMIAPEGI xmlMIAPEGI = factory.createGIMIAPEGI();

		addMiapeData(xmlMIAPEGI);

		Set<ImageGelInformatics> images = document.getImages();
		if (images != null)
			addImages(xmlMIAPEGI.getGIImage());

		Set<AnalysisDesign> analysisDesigns = document.getAnalysisDesigns();
		if (analysisDesigns != null)
			addAnalysisDesigns(xmlMIAPEGI.getGIAnalysisDesign());

		Set<ImageAnalysisSoftware> imagePreparationSoftwares = document
				.getImagePreparationSoftwares();
		if (imagePreparationSoftwares != null)
			addImagePreparationSoftwares(xmlMIAPEGI.getGIImagePreparationSoftware());

		Set<ImagePreparationStep> imagePreparationSteps = document.getImagePreparationSteps();
		if (imagePreparationSteps != null)
			addImagePreparationStep(xmlMIAPEGI.getGIImagePreparationStep());

		Set<ImageProcessing> imageProcessings = document.getImageProcessings();
		if (imageProcessings != null)
			addImageProcessings(xmlMIAPEGI.getGIImageProcessing());

		Set<ImageAnalysisSoftware> imageAnalysisSoftwares = document.getImageAnalysisSoftwares();
		if (imageAnalysisSoftwares != null)
			addImageAnalysisSoftware(xmlMIAPEGI.getGIImageAnalysisSoftware());

		Set<DataAnalysis> dataAnalysises = document.getDataAnalysises();
		if (dataAnalysises != null)
			addDataAnalysis(xmlMIAPEGI.getGIDataAnalysis());

		Set<DataExtraction> dataExtractions = document.getDataExtractions();
		if (dataExtractions != null)
			addDataExtraction(xmlMIAPEGI.getGIDataExtraction());

		Set<DataReporting> dataReportings = document.getDataReportings();
		if (dataReportings != null)
			addDataReporting(xmlMIAPEGI.getGIDataReporting());

		Set<GIAdditionalInformation> additionalInformations = document.getAdditionalInformations();
		if (additionalInformations != null)
			addAdditionalInformation(xmlMIAPEGI.getGIAdditionalInformation());

		return xmlMIAPEGI;
	}

	private void addImages(List<GIImage> xmlImages) {
		final Set<ImageGelInformatics> images = document.getImages();
		if (images != null) {
			for (ImageGelInformatics image : images) {
				GIImage xmlImage = new ImageAdapter(image, factory, cvFactory).adapt();
				xmlImages.add(xmlImage);
			}
		}
	}

	private void addAdditionalInformation(List<ParamType> xmlAddInfos) {
		final Set<GIAdditionalInformation> additionalInformations = document
				.getAdditionalInformations();
		if (additionalInformations != null) {
			for (GIAdditionalInformation addInfo : additionalInformations) {
				ParamType xmlPreparation = new AdditionalInformationAdapter(addInfo, factory,
						cvFactory).adapt();
				xmlAddInfos.add(xmlPreparation);
			}
		}
	}

	private void addImagePreparationStep(List<GIImagePreparationStep> xmlPreparations) {
		final Set<ImagePreparationStep> imagePreparationSteps = document.getImagePreparationSteps();
		if (imagePreparationSteps != null) {
			for (ImagePreparationStep preparation : imagePreparationSteps) {
				GIImagePreparationStep xmlPreparation = new ImagePreparationStepAdapter(
						preparation, factory, cvFactory).adapt();
				xmlPreparations.add(xmlPreparation);
			}
		}
	}

	private void addImagePreparationSoftwares(List<MIAPESoftwareType> giImagePreparationSoftware) {
		if (document.getImagePreparationSoftwares() != null) {
			for (ImageAnalysisSoftware software : document.getImagePreparationSoftwares()) {
				MIAPESoftwareType xmlSoftware = new SoftwareAdapter(software, factory, cvFactory)
						.adapt();
				giImagePreparationSoftware.add(xmlSoftware);
			}
		}
	}

	private void addDataReporting(List<GIDataReporting> giDataReporting) {
		final Set<DataReporting> dataReportings = document.getDataReportings();
		if (dataReportings != null) {
			for (DataReporting dataReporting : dataReportings) {
				GIDataReporting xmlDataReporting = new DataReportingAdapter(dataReporting, factory,
						cvFactory).adapt();
				giDataReporting.add(xmlDataReporting);
			}
		}
	}

	private void addDataExtraction(List<GIDataExtraction> giDataExtraction) {
		final Set<DataExtraction> dataExtractions = document.getDataExtractions();
		if (dataExtractions != null) {
			for (DataExtraction dataExtraction : dataExtractions) {
				GIDataExtraction xmlDataExtraction = new DataExtractionAdapter(dataExtraction,
						factory, cvFactory).adapt();
			}
		}
	}

	private void addDataAnalysis(List<GIDataAnalysis> giDataAnalysis) {
		final Set<DataAnalysis> dataAnalysises = document.getDataAnalysises();
		if (dataAnalysises != null) {
			for (DataAnalysis dataAnalysis : dataAnalysises) {
				GIDataAnalysis xmlDataAnalysis = new DataAnalysisAdapter(dataAnalysis, factory,
						cvFactory).adapt();
				;

				addImageProcessingSoftwares(xmlDataAnalysis.getGIDataAnalysisSoftware(),
						dataAnalysis.getDataAnalysisSoftwares());

				for (Algorithm algorithm : dataAnalysis.getDataAnalysisTransformations()) {
					xmlDataAnalysis.getGIDataAnalysisTransformation().add(
							new AlgorithmAdapter(algorithm, factory, cvFactory).adapt());
				}

				giDataAnalysis.add(xmlDataAnalysis);
			}
		}
	}

	private void addImageProcessings(List<GIImageProcessing> imageProcessings) {
		final Set<ImageProcessing> imageProcessings2 = document.getImageProcessings();
		if (imageProcessings2 != null) {
			for (ImageProcessing processing : imageProcessings2) {
				GIImageProcessing xmlImageProcessing = new ImageProcessingAdapter(processing,
						factory, cvFactory).adapt();
				addImageProcessingInputImages(xmlImageProcessing.getGIProcessingInputImage(),
						processing.getInputImages());
				addImageProcessingSoftwares(xmlImageProcessing.getGIImageProcessingSoftware(),
						processing.getImageProcessingSoftwares());
				addImageProcessingSteps(xmlImageProcessing.getGIImageProcessingStep(),
						processing.getImageProcessingSteps());
				imageProcessings.add(xmlImageProcessing);
			}
		}
	}

	private void addImageProcessingInputImages(List<GIProcessingInputImage> giInputImage,
			Set<ImageGelInformatics> inputImages) {
		if (inputImages != null) {
			for (ImageGelInformatics inputImage : inputImages) {
				GIProcessingInputImage xmlInputImage = new ProcessingInputImageAdapter(inputImage,
						factory).adapt();
				giInputImage.add(xmlInputImage);
			}
		}
	}

	private void addImageProcessingSteps(
			List<GIImageProcessingAlgorithmType> giImageAnalysisProcessingAlgorithm,
			Set<ImageProcessingStep> analysisProcessingSteps) {
		if (analysisProcessingSteps != null) {
			for (ImageProcessingStep analysisProcessingStep : analysisProcessingSteps) {
				GIImageProcessingAlgorithmType xmlProcessingStep = new AnalysisProcessingAlgorithmAdapter(
						analysisProcessingStep, factory, cvFactory).adapt();
				giImageAnalysisProcessingAlgorithm.add(xmlProcessingStep);
			}
		}
	}

	private void addImageProcessingSoftwares(List<MIAPESoftwareType> xmlSoftwares,
			Set<ImageAnalysisSoftware> imageProcessingSoftwares) {
		if (imageProcessingSoftwares != null) {
			for (ImageAnalysisSoftware imageProcessingSoftware : imageProcessingSoftwares) {
				MIAPESoftwareType xmlSoftware = new SoftwareAdapter(imageProcessingSoftware,
						factory, cvFactory).adapt();
				xmlSoftwares.add(xmlSoftware);
			}
		}

	}

	private void addImageAnalysisSoftware(List<MIAPESoftwareType> giAnalysisSoftware) {
		final Set<ImageAnalysisSoftware> imageAnalysisSoftwares = document
				.getImageAnalysisSoftwares();
		if (imageAnalysisSoftwares != null) {
			for (ImageAnalysisSoftware software : imageAnalysisSoftwares) {
				MIAPESoftwareType xmlSoftware = new SoftwareAdapter(software, factory, cvFactory)
						.adapt();
				giAnalysisSoftware.add(xmlSoftware);
			}
		}

	}

	private void addAnalysisDesigns(List<GIAnalysisDesign> xmlAnalysisDesigns) {
		if (document.getAnalysisDesigns() != null) {
			for (AnalysisDesign analysisDesign : document.getAnalysisDesigns()) {
				GIAnalysisDesign xmlAnalysisDesign = factory.createGIAnalysisDesign();
				xmlAnalysisDesign.setGroups(analysisDesign.getGroups());
				xmlAnalysisDesign.setName(analysisDesign.getName());
				xmlAnalysisDesign.setExternalStandard(analysisDesign.getExternalStandard());
				xmlAnalysisDesign.setWithinSampleStandard(analysisDesign.getWithinSampleStandard());
				xmlAnalysisDesign.setStandards(analysisDesign.getStandard());
				xmlAnalysisDesign.setReplicates(analysisDesign.getReplicates());
				xmlAnalysisDesign.setType(analysisDesign.getType());
				xmlAnalysisDesigns.add(xmlAnalysisDesign);
			}
		}
	}

	private void addMiapeData(GIMIAPEGI xmlMIAPEGI) {
		final int id = document.getId();
		if (id > 0) {
			xmlMIAPEGI.setId(id);
		} else {
			xmlMIAPEGI.setId(-1);
		}
		final MiapeDate date = document.getDate();
		if (date != null)
			xmlMIAPEGI.setDate(date.getValue());
		else
			xmlMIAPEGI.setDate(null);

		xmlMIAPEGI.setElectrophoresisType(cvFactory.createCV(document.getElectrophoresisType(),
				null, ElectrophoresisType.getInstance(cvFactory.getCvManager())));
		final GEContact contact = document.getContact();
		if (contact != null)
			xmlMIAPEGI.setGIContact(new ContactAdapter(contact, factory, cvFactory).adapt());
		final Date modificationDate = document.getModificationDate();
		if (modificationDate != null)
			xmlMIAPEGI.setModificationDate(new DateAdapter(modificationDate).adapt());

		xmlMIAPEGI.setName(document.getName());
		xmlMIAPEGI.setAttachedFileLocation(document.getAttachedFileLocation());
		final Project project = document.getProject();
		if (project != null)
			xmlMIAPEGI.setMIAPEProject(new ProjectAdapter(project, factory).adapt());
		final Boolean template = document.getTemplate();
		if (template != null)
			xmlMIAPEGI.setTemplate(template);
		else
			xmlMIAPEGI.setTemplate(Boolean.FALSE);

		xmlMIAPEGI.setVersion(document.getVersion());
		xmlMIAPEGI.setReference(document.getReference());
		xmlMIAPEGI.setMIAPEGERef(document.getGEDocumentReference());

	}

}
